<?php

namespace Protobuf\Compiler\Command;

use Exception;
use RuntimeException;
use Protobuf\Stream;
use Psr\Log\LogLevel;
use Protobuf\Compiler\Compiler;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Plugin to generate PHP classes from stdin generated by protoc
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 */
class PluginCommand extends Command
{

    /**
     * @var \Protobuf\Stream
     */
    private $stream;

    /**
     * @param \Protobuf\Stream $stream
     */
    public function setStream(Stream $stream)
    {
        $this->stream = $stream;
    }

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('protobuf:plugin')
            ->setDescription('Plugin to generate PHP classes from stdin generated by protoc');
    }

    /**
     * @param \Protobuf\Stream $stream
     */
    protected function writeStream(Stream $stream)
    {
        // OutputInterface#write messes with the content
        fwrite(STDOUT, $stream);
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if ($this->stream === null) {
            throw new RuntimeException("Unable to read standard input.");
        }

        $compiler = $this->createCompiler($output);
        $response = $compiler->compile($this->stream);

        $this->writeStream($response);
    }

    /**
     * @param \Symfony\Component\Console\Output\OutputInterface $output
     *
     * @return \Protobuf\Compiler\Compiler
     */
    protected function createCompiler(OutputInterface $output)
    {
        $logger   = $this->createConsoleLogger($output);
        $compiler = new Compiler($logger);

        return $compiler;
    }

    /**
     * @param \Symfony\Component\Console\Output\OutputInterface $output
     *
     * @return \Symfony\Component\Console\Logger\ConsoleLogger
     */
    protected function createConsoleLogger(OutputInterface $output)
    {
        return new ConsoleLogger(
            $output,
            [
                // aways output notice, info and debug
                LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL,
                LogLevel::INFO   => OutputInterface::VERBOSITY_NORMAL,
                LogLevel::DEBUG  => OutputInterface::VERBOSITY_NORMAL
            ],
            [
                // redirect messages to stderr
                LogLevel::WARNING => ConsoleLogger::INFO,
                LogLevel::NOTICE  => ConsoleLogger::ERROR,
                LogLevel::INFO    => ConsoleLogger::ERROR,
                LogLevel::DEBUG   => ConsoleLogger::ERROR
            ]
        );
    }
}
